package com.zodiac.app.szse.d.d0602.d060201;

import com.alibaba.fastjson.JSONObject;
import com.github.lzm320a99981e.component.dataautomation.AbstractExtractor;
import com.github.lzm320a99981e.zodiac.component.tools.DateUtils;
import lombok.Data;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.function.Function;

/**
 * 深圳证券交易所 >> 信息披露 >> 上市公司信息 >> 定期报告
 */
@Component
public class D060201Extractor extends AbstractExtractor<D060201Extractor.Request, List> {
    private final RestTemplate restTemplate = new RestTemplate();

    @Retryable(value = Exception.class, maxAttempts = 5, backoff = @Backoff(delay = 1000, multiplier = 2))
    @Override
    public List extract(Request request) {
        JSONObject response = doRequest(request);
        if (Objects.isNull(response) || Objects.equals(0, response.getIntValue("announceCount"))) {
            return null;
        }
        return response.getJSONArray("data");
    }

    /**
     * 统计数量
     *
     * @param request
     * @return
     */
    public int count(Request request) {
        return Objects.requireNonNull(doRequest(request)).getIntValue("announceCount");
    }

    private JSONObject doRequest(Request request) {
        try {
            Thread.sleep(Integer.valueOf(RandomStringUtils.random(1, "12")) * 100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return restTemplate.postForObject(Request.getUrl(), request, JSONObject.class);
    }

    @Data
    public static class Request {
        private List<String> channelCode = Collections.singletonList("fixed_disc");
        /**
         * 股票代码
         */
        private List<String> stock = new ArrayList<>();
        /**
         * 行业
         */
        private List<String> bigIndustryCode = new ArrayList<>();
        /**
         * 板块
         */
        private List<String> plateCode = new ArrayList<>();
        /**
         * 报告类别
         */
        private List<String> bigCategoryId = new ArrayList<>();
        /**
         * 日期范围
         */
        private List<String> seDate = new ArrayList<>(2);
        /**
         * 每页大小(最大为30)
         */
        private int pageSize = 30;
        /**
         * 页码
         */
        private int pageNum = 1;
        /**
         * 过滤条件
         */
        private Function<D060201Model, Boolean> filter = m -> true;

        public Request() {
        }

        public static Request create(ReportCategory reportCategory) {
            Request instance = new Request();
            instance.getBigCategoryId().add(reportCategory.getValue());
            return instance;
        }

        public static Request create(String stockCode) {
            Request instance = new Request();
            instance.setStock(Collections.singletonList(stockCode));
            return instance;
        }

        public static Request create(ReportCategory reportCategory, String stockCode) {
            Request instance = new Request();
            instance.getBigCategoryId().add(reportCategory.getValue());
            instance.setStock(Collections.singletonList(stockCode));
            return instance;
        }

        public Request pageNum(int pageNum) {
            setPageNum(pageNum);
            return this;
        }

        public Request startDate(Date startDate) {
            this.seDate.add(DateUtils.formatUseYmd(startDate));
            return this;
        }

        public Request endDate(Date endDate) {
            this.seDate.add(DateUtils.formatUseYmd(endDate));
            return this;
        }

        public Request industries(Industry... industries) {
            for (Industry item : industries) {
                this.bigIndustryCode.add(item.name());
            }
            return this;
        }

        public Request boards(Board... boards) {
            for (Board item : boards) {
                this.plateCode.add(item.getValue());
            }
            return this;
        }

        public Request reportCategories(ReportCategory... reportCategories) {
            for (ReportCategory item : reportCategories) {
                this.bigCategoryId.add(item.getValue());
            }
            return this;
        }

        static String getUrl() {
            return "http://www.szse.cn/api/disc/announcement/annList?random=" + Math.random();
        }
    }

    /**
     * 行业
     */
    public enum Industry {
        A("农林牧渔"),
        B("采矿业"),
        C("制造业"),
        D("水电煤气"),
        E("建筑业"),
        F("批发零售"),
        G("运输仓储"),
        H("住宿餐饮"),
        I("信息技术"),
        J("金融业"),
        K("房地产"),
        L("商务服务"),
        M("科研服务"),
        N("公共环保"),
        O("居民服务"),
        P("教育"),
        Q("卫生"),
        R("文化传播"),
        S("综合");
        private String description;

        Industry(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    /**
     * 板块
     */
    public enum Board {
        ZHU("11"),
        ZHONG("12"),
        CHUANG("16");
        private String value;

        Board(String value) {
            this.value = value;
        }

        public String getValue() {
            return this.value;
        }
    }

    /**
     * 报告类型
     */
    public enum ReportCategory {
        Q1("一季度报告", "010305", "03"),
        Q2("半年度报告", "010303", "06"),
        Q3("三季度报告", "010307", "09"),
        Q4("年度报告", "010301", "12");
        private String description;
        private String value;
        private String month;

        ReportCategory(String description, String value, String month) {
            this.description = description;
            this.value = value;
            this.month = month;
        }

        public String getDescription() {
            return description;
        }

        public String getValue() {
            return this.value;
        }

        public String getMonth() {
            return month;
        }

        public static ReportCategory of(String value) {
            return EnumUtils.getEnumList(ReportCategory.class).stream().filter(item -> Objects.equals(item.getValue(), value)).findFirst().orElse(null);
        }
    }
}
